package edu.nju.mutest.mutator;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.expr.BinaryExpr;
import com.github.javaparser.ast.expr.Expression;
import edu.nju.mutest.util.CollectorUtil;
import edu.nju.mutest.visitor.collector.BinaryExprCollector;

import static com.github.javaparser.ast.expr.BinaryExpr.Operator.*;

import java.util.List;


public class BinaryMutatorDemo extends AbstractMutator {

    private final BinaryExpr.Operator[] targetOps = {
            PLUS, MINUS, MULTIPLY, DIVIDE
    };

    public BinaryMutatorDemo(CompilationUnit cu) {
        super(cu);
    }

    @Override
    public List<CompilationUnit> mutate() {
        if (this.mutPoints == null)
            mutPoints = CollectorUtil.collect(new BinaryExprCollector(), this.origCU);

        // Modify each mutation points.
        for (Expression mp : mutPoints) {

            // Generate simple mutation. Each mutant contains only one
            // mutated point.
            for (BinaryExpr.Operator targetOp : targetOps) {
                CompilationUnit mutCU = mutateOnce((BinaryExpr)mp, targetOp);
                if (mutCU != null) {
                    mutants.add(mutCU);
                }
            }
        }
        return mutants;
    }

    /**
     * Replace the operator with a given one
     */
    private CompilationUnit mutateOnce(BinaryExpr mp, BinaryExpr.Operator op) {
        // This is a polluted operation. So we preserve the original operator for recovering.
        BinaryExpr.Operator origOp = mp.getOperator();
        if (origOp.equals(op))
            return null;

        mp.setOperator(op);
        // deep copy
        CompilationUnit mutCU =  this.origCU.clone();

        // Recovering
        mp.setOperator(origOp);

        return mutCU;
    }
}
